#pragma once

#include <memory>

template <typename T>
class Matrix {
 public:
  Matrix() : _row(0), _col(0), _data(nullptr) {}
  Matrix(size_t row, size_t col) : _row(row), _col(col) {
    _data = std::shared_ptr<T>(new T[row * col]);
  }
  T &operator()(size_t i, size_t j) {
    return _data[i * _col + j];
  }
  const T &operator()(size_t i, size_t j) const {
    return _data[i * _col + j];
  }
  T *operator[](size_t i) {
    return _data.get() + i * _col;
  }
  const T *operator[](size_t i) const {
    return _data.get() + i * _col;
  }
  void Reverse() {
    size_t new_row = _col;
    size_t new_col = _row;
    std::shared_ptr<T> new_data(new T[new_row * new_col]);
    for (size_t i = 0; i < _row; ++i) {
      for (size_t j = 0; j < _col; ++j) {
        new_data[j * new_row + i] = _data[i * _col + j];
      }
    }
    _data = new_data;
    _row = new_row;
    _col = new_col;
  }
  size_t Row() const {
    return _row;
  }
  size_t Col() const {
    return _col;
  }

 private:
  size_t _row;
  size_t _col;
  std::shared_ptr<T> _data;
};
